/* Copyright(c) 2010- Siro-info Co.(http://www.siro-info.com)
 * All rights reserved.
 */
package com.siro.pm.ui.main;

import java.text.DateFormatSymbols;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;

import com.siro.pm.I18nManager;
import com.siro.pm.PmApplication;
import com.siro.pm.model.Attendance;
import com.siro.pm.model.Developer;
import com.siro.pm.model.UserAttendance;
import com.siro.pm.model.provider.AttendanceProvider;
import com.siro.pm.ui.detail.AttendanceDetailPage;
import com.vaadin.addon.calendar.event.CalendarEvent;
import com.vaadin.addon.calendar.ui.Calendar;
import com.vaadin.addon.calendar.ui.CalendarComponentEvents.BackwardEvent;
import com.vaadin.addon.calendar.ui.CalendarComponentEvents.EventClick;
import com.vaadin.addon.calendar.ui.CalendarComponentEvents.EventClickHandler;
import com.vaadin.addon.calendar.ui.CalendarComponentEvents.ForwardEvent;
import com.vaadin.addon.calendar.ui.CalendarComponentEvents.RangeSelectEvent;
import com.vaadin.addon.calendar.ui.CalendarComponentEvents.RangeSelectHandler;
import com.vaadin.addon.calendar.ui.handler.BasicBackwardHandler;
import com.vaadin.addon.calendar.ui.handler.BasicForwardHandler;
import com.vaadin.terminal.Sizeable;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

/**
 * Class Declaration:
 * 
 * @version v1.0
 * @since AttendancePage.java v1.0
 */
public class AttendancePage extends VerticalLayout {
	private static final long serialVersionUID = -6128269023164047466L;

	private GregorianCalendar gregorianCalendar = new GregorianCalendar();
	Date today = new Date();
	private Date currentMonthsFirstDate = null;
	private AttendanceProvider datasource = new AttendanceProvider();

	private Calendar calendar;
	private Label label = new Label("");
	private Button prev;
	private Button next;
	private Button commit;

	private Button work;
	private Button rest;
	private Button travel;
	private Button personalLeave;
	private Button sickLeave;

	private String userName;
	public String lastWhere;
	public String lastBankName;

	public AttendancePage() {
		super();
	}

	public void createContents() {
		setSizeFull();
		setSpacing(true);
		setMargin(true, true, true, true);
		gregorianCalendar.setTime(today);
		gregorianCalendar.get(GregorianCalendar.MONTH);

		DateFormatSymbols s = new DateFormatSymbols(Locale.getDefault());
		String month = s.getShortMonths()[gregorianCalendar
				.get(GregorianCalendar.MONTH)];
		label.setValue(month + " "
				+ gregorianCalendar.get(GregorianCalendar.YEAR));

		int rollAmount = gregorianCalendar.get(GregorianCalendar.DAY_OF_MONTH) - 1;
		gregorianCalendar.add(GregorianCalendar.DAY_OF_MONTH, -rollAmount);
		currentMonthsFirstDate = gregorianCalendar.getTime();
		gregorianCalendar.add(GregorianCalendar.MONTH, 1);
		gregorianCalendar.add(GregorianCalendar.DATE, -1);

		setUserName(((Developer) PmApplication.getDefault().getUser())
				.getName());
		datasource.setUserName(userName);
		calendar = new Calendar(datasource);
		calendar.setSizeFull();
		calendar.setStartDate(currentMonthsFirstDate);
		calendar.setEndDate(gregorianCalendar.getTime());
		calendar.setImmediate(true);
		addListner4Calendar();

		prev = new Button(I18nManager.getMessage("attendance.lastmonth"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						gregorianCalendar.setTime(currentMonthsFirstDate);
						gregorianCalendar.add(GregorianCalendar.MONTH, -1);
						currentMonthsFirstDate = gregorianCalendar.getTime();
						calendar.setStartDate(currentMonthsFirstDate);
						DateFormatSymbols s = new DateFormatSymbols(Locale
								.getDefault());
						String month = s.getShortMonths()[gregorianCalendar
								.get(GregorianCalendar.MONTH)];
						label.setValue(month + " "
								+ gregorianCalendar.get(GregorianCalendar.YEAR));
						gregorianCalendar.add(GregorianCalendar.MONTH, 1);
						gregorianCalendar.add(GregorianCalendar.DATE, -1);
						calendar.setEndDate(gregorianCalendar.getTime());
					}
				});
		next = new Button(I18nManager.getMessage("attendance.nextmonth"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						gregorianCalendar.setTime(currentMonthsFirstDate);
						gregorianCalendar.add(GregorianCalendar.MONTH, 1);
						currentMonthsFirstDate = gregorianCalendar.getTime();
						calendar.setStartDate(currentMonthsFirstDate);

						DateFormatSymbols s = new DateFormatSymbols(Locale
								.getDefault());
						String month = s.getShortMonths()[gregorianCalendar
								.get(GregorianCalendar.MONTH)];
						label.setValue(month + " "
								+ gregorianCalendar.get(GregorianCalendar.YEAR));

						gregorianCalendar.add(GregorianCalendar.MONTH, 1);
						gregorianCalendar.add(GregorianCalendar.DATE, -1);
						calendar.setEndDate(gregorianCalendar.getTime());
					}
				});
		commit = new Button(I18nManager.getMessage("button.commit"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						commitAttendanceData();
					}
				});

		work = new Button(I18nManager.getMessage("attendance.work"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						Attendance.CURRENT_ATTENDANCE_STATUS = Attendance.ATTENDANCE_STATUS_WORK;
					}
				});
		rest = new Button(I18nManager.getMessage("attendance.rest"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						Attendance.CURRENT_ATTENDANCE_STATUS = Attendance.ATTENDANCE_STATUS_REST;
					}
				});
		travel = new Button(I18nManager.getMessage("attendance.travel"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						Attendance.CURRENT_ATTENDANCE_STATUS = Attendance.ATTENDANCE_STATUS_TRAVEL;
					}
				});
		personalLeave = new Button(
				I18nManager.getMessage("attendance.personalLeave"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						Attendance.CURRENT_ATTENDANCE_STATUS = Attendance.ATTENDANCE_STATUS_PERSONALLEAVE;
					}
				});
		sickLeave = new Button(I18nManager.getMessage("attendance.sickLeave"),
				new Button.ClickListener() {
					private static final long serialVersionUID = 1L;

					public void buttonClick(ClickEvent event) {
						Attendance.CURRENT_ATTENDANCE_STATUS = Attendance.ATTENDANCE_STATUS_SICKLEAVE;
					}
				});

		HorizontalLayout tools = new HorizontalLayout();
		tools.setWidth(100, Sizeable.UNITS_PERCENTAGE);
		tools.setSpacing(true);

		HorizontalLayout controls = new HorizontalLayout();
		controls.setSpacing(true);
		controls.addComponent(prev);
		controls.setComponentAlignment(prev, Alignment.MIDDLE_LEFT);
		controls.addComponent(label);
		controls.setComponentAlignment(label, Alignment.MIDDLE_LEFT);
		controls.addComponent(next);
		controls.setComponentAlignment(next, Alignment.MIDDLE_LEFT);
		controls.addComponent(commit);
		controls.setComponentAlignment(commit, Alignment.MIDDLE_LEFT);
		tools.addComponent(controls);
		tools.setComponentAlignment(controls, Alignment.MIDDLE_LEFT);

		HorizontalLayout status = new HorizontalLayout();
		status.setSpacing(true);
		status.addComponent(work);
		status.addComponent(rest);
		status.addComponent(travel);
		status.addComponent(personalLeave);
		status.addComponent(sickLeave);
		tools.addComponent(status);
		tools.setComponentAlignment(status, Alignment.MIDDLE_RIGHT);

		addComponent(tools);
		setComponentAlignment(tools, Alignment.MIDDLE_LEFT);
		addComponent(calendar);
		setExpandRatio(calendar, 1);
	}

	private void addListner4Calendar() {
		// Make sure the date is in the same year as today
		calendar.setHandler(new BasicBackwardHandler() {

			private static final long serialVersionUID = 4473964449621632059L;

			@Override
			protected void setDates(BackwardEvent event, Date start, Date end) {
				java.util.Calendar calendar = event.getComponent()
						.getInternalCalendar();
				if (isThisYear(calendar, end) && isThisYear(calendar, start)) {
					super.setDates(event, start, end);
				}
			}
		});

		// Make sure the date is in the same year as today
		calendar.setHandler(new BasicForwardHandler() {

			private static final long serialVersionUID = -4718745721954015665L;

			@Override
			protected void setDates(ForwardEvent event, Date start, Date end) {
				java.util.Calendar calendar = event.getComponent()
						.getInternalCalendar();
				if (isThisYear(calendar, start) && isThisYear(calendar, end)) {
					super.setDates(event, start, end);
				}
			}
		});

		calendar.setHandler(new EventClickHandler() {
			private static final long serialVersionUID = 4885109097771786499L;

			public void eventClick(EventClick event) {
				Attendance attendance = (Attendance) event.getCalendarEvent();
				showEventPopup(attendance);
			}
		});

		calendar.setHandler(new RangeSelectHandler() {
			private static final long serialVersionUID = -2226369212761574674L;

			public void rangeSelect(RangeSelectEvent event) {
				Date start = event.getStart();
				Date end = event.getEnd();
				if (!datasource.containsAttendance(start)) {
					Attendance attendance = createNewEvent(start, end);
					if (attendance.getStatus().equals(
							Attendance.ATTENDANCE_STATUS_TRAVEL)) {
						showEventPopup(attendance);
					}
					datasource.addEvent(attendance);
					refresh();
				}
			}
		});
	}

	protected void showEventPopup(Attendance attendance) {
		AttendanceDetailPage attendanceDetailPage = new AttendanceDetailPage();
		attendanceDetailPage.setAttendance(attendance);
		attendanceDetailPage.setAttendancePage(this);
		attendanceDetailPage.createContents();
		Window dvpDetailWindow = new Window(
				I18nManager.getMessage("attendance.base.info"));
		dvpDetailWindow.setModal(true);
		dvpDetailWindow.setWidth("800px");
		dvpDetailWindow.setHeight("80%");
		attendanceDetailPage.setWindow(dvpDetailWindow);
		dvpDetailWindow.addComponent(attendanceDetailPage);
		getWindow().addWindow(dvpDetailWindow);
	}

	public void refresh() {
		calendar.requestRepaint();
	}

	protected void commitAttendanceData() {
		List<CalendarEvent> attendances = datasource.getCurrentAllEvents();
		for (CalendarEvent calendarEvent : attendances) {
			Attendance attendance = (Attendance) calendarEvent;
			UserAttendance uAttendance = attendance.toUserAttendance(userName);
			UserAttendance.updateUserAttendance(uAttendance);
		}
	}

	public static boolean isThisYear(java.util.Calendar calendar, Date date) {
		calendar.setTime(new Date());
		int thisYear = calendar.get(java.util.Calendar.YEAR);
		calendar.setTime(date);
		return calendar.get(java.util.Calendar.YEAR) == thisYear;
	}

	public static boolean isThisMonth(java.util.Calendar calendar, Date date) {
		calendar.setTime(new Date());
		int thisMonth = calendar.get(java.util.Calendar.MONTH);
		calendar.setTime(date);
		return calendar.get(java.util.Calendar.MONTH) == thisMonth;
	}

	private Attendance createNewEvent(Date startDate, Date endDate) {
		Attendance attendance = new Attendance();
		if (Attendance.CURRENT_ATTENDANCE_STATUS
				.equals(Attendance.ATTENDANCE_STATUS_WORK)) {
			attendance.setStatus(Attendance.ATTENDANCE_STATUS_WORK);
		} else if (Attendance.CURRENT_ATTENDANCE_STATUS
				.equals(Attendance.ATTENDANCE_STATUS_REST)) {
			attendance.setStatus(Attendance.ATTENDANCE_STATUS_REST);
		} else if (Attendance.CURRENT_ATTENDANCE_STATUS
				.equals(Attendance.ATTENDANCE_STATUS_TRAVEL)) {
			attendance.setStatus(Attendance.ATTENDANCE_STATUS_TRAVEL);
		} else if (Attendance.CURRENT_ATTENDANCE_STATUS
				.equals(Attendance.ATTENDANCE_STATUS_PERSONALLEAVE)) {
			attendance.setStatus(Attendance.ATTENDANCE_STATUS_PERSONALLEAVE);
		} else if (Attendance.CURRENT_ATTENDANCE_STATUS
				.equals(Attendance.ATTENDANCE_STATUS_SICKLEAVE)) {
			attendance.setStatus(Attendance.ATTENDANCE_STATUS_SICKLEAVE);
		}
		attendance.setStart(startDate);
		attendance.setEnd(endDate);
		return attendance;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

}
